package cn.cupster.floatwindowdemo

import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import androidx.annotation.Nullable
import android.graphics.BitmapFactory
import android.graphics.PixelFormat
import android.os.Build
import android.provider.Settings
import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.view.View.OnTouchListener
import android.view.animation.LinearInterpolator
import java.lang.Exception
import kotlin.math.abs


/**
 * step-03:
 *
 * @author HB.zyy酸菜鱼
 * @date 2021-08-13
 */
class FloatWindowService : Service() {

    companion object{
        private const val TAG = "FloatWindowService"
    }

    private var windowManager: WindowManager? = null
    private var layoutParams: WindowManager.LayoutParams? = null
    private var mView: View? = null
    private var lstFilePaths: ArrayList<String>? = null
    private var currentIndex = 0
    private var screenWidth = 0
    private var screenHeight = 0
    private var mTouchSlop = 1
    private var mImgMoveToEdgeAnim: ValueAnimator? = null
    @Nullable
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        //加载窗口布局
        initWindow(intent)
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        //移除窗口布局
        windowManager?.removeView(mView)
        super.onDestroy()
    }

    private fun getContext(): Context{
        return this
    }

    private fun initWindow(intent: Intent) {
        mTouchSlop = ViewConfiguration.get(this).scaledTouchSlop
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (Settings.canDrawOverlays(this)) {
                //获取WindowManager服务
                windowManager = getSystemService(WINDOW_SERVICE) as WindowManager

                //取得屏幕尺寸
                val dm = DisplayMetrics()
                windowManager?.let { window ->
                    window.getDefaultDisplay().getMetrics(dm)
                    screenWidth = dm.widthPixels
                    screenHeight = dm.heightPixels
                    Log.e(TAG, "initWindow: screenWidth=$screenWidth,screenHeight=$screenHeight" )
                    //设置LayoutParams
                    layoutParams = WindowManager.LayoutParams()
                    layoutParams?.let {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                            it.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
                        } else {
                            it.type = WindowManager.LayoutParams.TYPE_PHONE
                        }
                        it.flags =
                            (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_FULLSCREEN
                                    or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
                        it.format = PixelFormat.RGBA_8888 //背景透明效果
//                        it.width = 512 //悬浮窗口长宽值，单位为 px 而非 dp
//                        it.height = 450
//                        it.gravity = 51 //想要x,y生效，一定要指定Gravity为top和left //Gravity.TOP | Gravity.LEFT
//                        it.x = 100 //启动位置
//                        it.y = 100

                        //设置悬浮窗口长宽数据
                        it.width = WindowManager.LayoutParams.WRAP_CONTENT
                        it.height = WindowManager.LayoutParams.WRAP_CONTENT
                        // 悬浮窗默认显示以左上角为起始坐标
                        // 悬浮窗默认显示以左上角为起始坐标
                        it.gravity = Gravity.RIGHT or Gravity.BOTTOM
                        //加载悬浮窗布局
                        mView = LayoutInflater.from(getContext() ).inflate(R.layout.float_window_layout , null ,false)
                        mView?.alpha = 0.9f
                        //设定悬浮窗控件
                        mView?.findViewById<View>(R.id.ivImg)?.setOnClickListener {
                            AppApplication.boolOpenFloatWindow = false
                            //切记添加关闭服务按钮事件，调用 stopSelf() 方法以关闭悬浮窗。
                            stopSelf()
                        }
                        setTouch(mView)
                        //接收传值
                        //....
                        //提交布局
                        window.addView(mView, it)
                    }
                }
            }
        }
    }
    var isMove = false

    //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchStartX = 0  //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchStartY = 0  //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchCurrentX = 0  //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchCurrentY = 0

    //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStartX = 0 //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStartY = 0  //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStopX = 0  //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStopY = 0

    //判断悬浮窗口是否移动，这里做个标记，防止移动后松手触发了点击事件
    private fun setTouch(view: View?) {
        view?.setOnTouchListener(object : OnTouchListener {
            private var dX = 0
            private var dY = 0
            override fun onTouch(view: View, event: MotionEvent): Boolean {
                layoutParams?.let { params ->
                    val action: Int = event.getAction()
                    when (action) {
                        MotionEvent.ACTION_DOWN -> {
                            isMove = false
                            mTouchStartX = event.getRawX().toInt()
                            mTouchStartY = event.getRawY().toInt()
                            mStartX = event.getRawX().toInt()
                            mStartY = event.getRawY().toInt()
                        }
                        MotionEvent.ACTION_MOVE -> {
                            mTouchCurrentX = event.getRawX().toInt()
                            mTouchCurrentY = event.getRawY().toInt()
                            params.x += mTouchStartX - mTouchCurrentX
                            params.y += mTouchStartY - mTouchCurrentY
                            windowManager?.updateViewLayout(mView, params)
                            mTouchStartX = mTouchCurrentX
                            mTouchStartY = mTouchCurrentY
                        }
                        MotionEvent.ACTION_UP -> {
                            mStopX = event.getRawX().toInt()
                            mStopY = event.getRawY().toInt()
                            if (Math.abs(mStartX - mStopX) >= mTouchSlop || Math.abs(mStartY - mStopY) >= mTouchSlop) {
                                isMove = true
                                if (params.x < screenWidth / 2 - mView!!.getMeasuredWidth() / 2
                                ) {
                                    moveSmallImageToEdge(0)
                                } else {
                                    moveSmallImageToEdge(
                                        screenWidth - mView!!.getMeasuredWidth()
                                    )
                                }
                            }
                        }
                        else -> {
                        }
                    }

                }
                //如果是移动事件不触发OnClick事件，防止移动的时候一放手形成点击事件
                //如果是移动事件不触发OnClick事件，防止移动的时候一放手形成点击事件
                return isMove
            }
        })
    }


    private fun moveSmallImageToEdge(desX: Int) {
        layoutParams?.let { wmParams->
            mImgMoveToEdgeAnim?.let {
                if (it != null && it.isRunning()) {
                    it.cancel()
                }
                mImgMoveToEdgeAnim = ValueAnimator.ofInt(wmParams.x, desX)
                it.duration = 200
                it.interpolator = LinearInterpolator()
                it.addUpdateListener(AnimatorUpdateListener { animation ->
                    wmParams.x = animation.animatedValue as Int
                    try {
                        windowManager?.updateViewLayout(mView, wmParams)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                })
                it.start()
            }
        }
    }

    private fun getBitmapOptions(filepath: String): BitmapFactory.Options? {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(filepath, options)
        return options
    }

    private fun showImage() {
        val options = getBitmapOptions(lstFilePaths!![currentIndex])
        layoutParams!!.width = Math.min(options!!.outWidth, screenWidth) //Math.min取得两个数据中的最小值
        layoutParams!!.height = Math.min(options.outHeight, screenHeight)
//        Glide.with(this).load(lstFilePaths!![currentIndex]).into(floatView.ivFloatMediaShow)
        windowManager!!.updateViewLayout(mView, layoutParams)
    }

}